<template>
  <view
      class="slide-confirm-container"
      :class="props.customClass ? `slide-confirm-container-${props.customClass}` : ''"
  >
    <view
        class="slide-track"
        :style="{
        background: progressBg,
        width: trackWidthValue,
        height: trackHeightValue,
        borderRadius: trackBorderRadius
      }"
        :disabled="props.disabled"
    >
      <view
          class="slide-handle"
          :style="{
          backgroundColor: handleBgColor,
          left: handlePosition + 'px',
          transition: isSliding ? 'none' : 'left 0.3s ease',
          boxShadow: handleShadowComputed,
          width: handleWidthValue,
          borderRadius: handleBorderRadius
        }"
          @touchstart="startSlide"
          @touchmove="onSlide"
          @touchend="endSlide"
          @touchcancel="endSlide"
          :disabled="props.disabled || isLoading"
      >
        <text class="handle-text" :style="{ color: handleTextColor }">
          {{ currentIcon }}
        </text>
      </view>
      <view class="slide-text" :style="{ color: textColorComputed }">
        {{ isConfirmed ? confirmText : slideText }}
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, computed, onMounted, watch, nextTick, getCurrentInstance } from 'vue'

// 组件props
const props = defineProps({
  width: {
    type: [Number, String],
    default: 300,
    validator: (val) => typeof val === 'number' || /^\d+(\.\d+)?(px|rpx|%|vw|vh|em|rem)$/.test(val)
  },
  height: {
    type: [Number, String],
    default: 30,
    validator: (val) => typeof val === 'number' || /^\d+(\.\d+)?(px|rpx|%|vw|vh|em|rem)$/.test(val)
  },
  slideText: {
    type: String,
    default: '滑动确认完工'
  },
  confirmText: {
    type: String,
    default: '确认完工'
  },
  handleText: {
    type: String,
    default: '→'
  },
  trackBgColor: {
    type: String,
    default: '#66e89a'
  },
  handleBgColor: {
    type: String,
    default: '#fff'
  },
  progressBgColor: {
    type: String,
    default: '#7bea1c'
  },
  textColor: {
    type: String,
    default: '#f8f5f5'
  },
  handleTextColor: {
    type: String,
    default: '#68ec9d'
  },
  successTextColor: {
    type: String,
    default: '#fff'
  },
  handleShadow: {
    type: String,
    default: '0 0 10px rgba(0, 0, 0, 0.1)'
  },
  successShadow: {
    type: String,
    default: '0 0 10px rgba(122, 194, 60, 0.5)'
  },
  resetTime: {
    type: Number,
    default: 3000,
    validator: (val) => val >= 0
  },
  disabled: {
    type: Boolean,
    default: false
  },
  showIcon: {
    type: Boolean,
    default: true
  },
  successIcon: {
    type: String,
    default: '✓'
  },
  slidingIcon: {
    type: String,
    default: '→'
  },
  loadingIcon: {
    type: String,
    default: '⟳'
  },
  customClass: {
    type: String,
    default: ''
  },
  borderRadius: {
    type: [Number, String],
    default: '25px',
    validator: (val) => typeof val === 'number' || /^\d+(\.\d+)?(px|rpx|%|vw|vh|em|rem)$/.test(val)
  },
  loading: {
    type: Boolean,
    default: false
  }
})

// 组件emits
const emits = defineEmits([
  'confirm',
  'reset',
  'slide',
  'loading-change'
])

// 状态变量
const trackWidth = ref(0)
const handleWidth = ref(0)
const handlePosition = ref(0)
const isSliding = ref(false)
const isConfirmed = ref(false)
const isLoading = ref(props.loading)
const progressBg = ref(props.trackBgColor)
const textColorComputed = ref(props.textColor)
const handleShadowComputed = ref(props.handleShadow)
const currentIcon = ref(props.slidingIcon)
const startClientX = ref(0)
const initialPosition = ref(0)
const isInitialized = ref(false)

// 计算属性
const maxPosition = computed(() => trackWidth.value - handleWidth.value)
const isComplete = computed(() => handlePosition.value >= maxPosition.value)
const isInteractive = computed(() => !props.disabled && !isLoading.value)
const trackWidthValue = computed(() => typeof props.width === 'number' ? `${props.width}px` : props.width)
const trackHeightValue = computed(() => typeof props.height === 'number' ? `${props.height}px` : props.height)
const handleWidthValue = computed(() => typeof props.width === 'number' ? `${Math.min(30, props.width * 0.3)}px` : '30px')
const trackBorderRadius = computed(() => typeof props.borderRadius === 'number' ? `${props.borderRadius}px` : props.borderRadius)
const handleBorderRadius = computed(() => typeof props.borderRadius === 'number' ? `${props.borderRadius}px` : props.borderRadius)

// 获取DOM元素尺寸
const getElementSize = (selector) => {
  return new Promise((resolve) => {
    const instance = getCurrentInstance()
    if (!instance) {
      console.warn('无法获取当前组件实例')
      resolve(null)
      return
    }

    const query = uni.createSelectorQuery().in(instance.proxy)
    query.select(selector).boundingClientRect((rect) => {
      resolve(rect)
    }).exec()
  })
}

// 初始化
const initializeComponent = async () => {
  try {
    const trackRect = await getElementSize('.slide-track')
    const handleRect = await getElementSize('.slide-handle')

    if (trackRect && handleRect) {
      trackWidth.value = trackRect.width
      handleWidth.value = handleRect.width
      console.log(`滑动组件初始化成功: 轨道宽度=${trackWidth.value}, 滑块宽度=${handleWidth.value}`)
      isInitialized.value = true
    } else {
      console.warn('无法获取滑动组件尺寸信息，使用默认值')
      trackWidth.value = typeof props.width === 'number' ? props.width : 300
      handleWidth.value = 30
    }
  } catch (error) {
    console.error('获取元素尺寸失败:', error)
    trackWidth.value = typeof props.width === 'number' ? props.width : 300
    handleWidth.value = 50
  }
}

onMounted(async () => {
  await initializeComponent()

  // 处理加载状态
  if (props.loading) {
    isLoading.value = true
    currentIcon.value = props.loadingIcon
    emits('loading-change', true)
  }
})

// 监听disabled属性变化
watch(() => props.disabled, (newVal) => {
  if (newVal && isSliding.value) {
    endSlide()
  }
})

// 监听loading属性变化
watch(() => props.loading, (newVal) => {
  isLoading.value = newVal
  if (newVal) {
    currentIcon.value = props.loadingIcon
    emits('loading-change', true)
  } else if (!isConfirmed.value) {
    currentIcon.value = props.slidingIcon
    emits('loading-change', false)
  }
})

// 开始滑动
const startSlide = (e) => {
  if (!isInteractive.value || isConfirmed.value) return

  isSliding.value = true
  initialPosition.value = handlePosition.value
  startClientX.value = e.touches[0].clientX
  currentIcon.value = props.slidingIcon

  emits('slide', {
    position: handlePosition.value,
    percent: (handlePosition.value / maxPosition.value) * 100,
    isComplete: false
  })
}

// 滑动过程
const onSlide = (e) => {
  if (!isSliding.value || !isInteractive.value || isConfirmed.value) return

  const touch = e.touches[0]
  const clientX = touch.clientX
  const deltaX = clientX - startClientX.value

  // 计算新位置
  let newPosition = initialPosition.value + deltaX

  // 限制滑块位置在轨道内
  newPosition = Math.max(0, Math.min(newPosition, maxPosition.value))
  handlePosition.value = newPosition

  // 更新进度条背景
  const percent = (newPosition / maxPosition.value) * 100
  progressBg.value = `linear-gradient(to right, ${props.progressBgColor} ${percent}%, ${props.trackBgColor} ${percent}%)`

  // 更新图标
  if (percent >= 90 && props.showIcon && !isLoading.value) {
    currentIcon.value = props.successIcon
  } else if (props.showIcon && !isLoading.value) {
    currentIcon.value = props.slidingIcon
  }

  // 发出滑动事件
  emits('slide', {
    position: newPosition,
    percent: percent,
    isComplete: percent >= 100
  })
}

// 结束滑动
const endSlide = () => {
  if (!isSliding.value) return

  isSliding.value = false

  if (isComplete.value && !isConfirmed.value && !isLoading.value) {
    // 验证通过
    handlePosition.value = maxPosition.value
    isConfirmed.value = true
    progressBg.value = props.progressBgColor
    textColorComputed.value = props.successTextColor
    handleShadowComputed.value = props.successShadow
    currentIcon.value = props.successIcon

    // 发出确认事件
    emits('confirm')

    // 如果设置了loading，则保持加载状态
    if (props.loading) {
      isLoading.value = true
      emits('loading-change', true)
    } else if (props.resetTime > 0) {
 /*     // 自动重置
      setTimeout(() => {
        resetSlide()
      }, props.resetTime)*/
    }
  } else {
    // 未达到要求，重置
    resetSlide()
  }
}

// 重置滑块
const resetSlide = () => {
  if (isSliding.value || isLoading.value) return

  handlePosition.value = 0
  isConfirmed.value = false
  progressBg.value = props.trackBgColor
  textColorComputed.value = props.textColor
  handleShadowComputed.value = props.handleShadow
  currentIcon.value = props.slidingIcon

  // 发出重置事件
  emits('reset')
}

// 暴露公共方法
const exposePublicMethods = {
  reset: resetSlide,
  confirm: () => {
    if (isConfirmed.value || isLoading.value) return

    handlePosition.value = maxPosition.value
    isConfirmed.value = true
    progressBg.value = props.progressBgColor
    textColorComputed.value = props.successTextColor
    handleShadowComputed.value = props.successShadow
    currentIcon.value = props.successIcon

    emits('confirm')
  },
  setLoading: (loading) => {
    isLoading.value = loading
    if (loading) {
      currentIcon.value = props.loadingIcon
      emits('loading-change', true)
    } else if (!isConfirmed.value) {
      currentIcon.value = props.slidingIcon
      emits('loading-change', false)
    }
  }
}

defineExpose(exposePublicMethods)
</script>

<style scoped>
.slide-confirm-container {
  width: 100%;
  display: flex;
  justify-content: center;
  margin: 5px 0 3px 0;
  user-select: none;
  -webkit-user-select: none;
}

.slide-track {
  position: relative;
  overflow: hidden;
  transition: background 0.3s ease;
}

.slide-handle {
  position: absolute;
  top: 0;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 2;
  transition: all 0.3s ease;
  transform: translateX(0);
}

.handle-text {
  font-size: 18px;
  font-weight: bold;
  transition: transform 0.3s ease;
}

.slide-text {
  position: absolute;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  z-index: 1;
  pointer-events: none;
  transition: color 0.3s ease;
  letter-spacing: 1px;
}

/* 禁用状态样式 */
.slide-track[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
}

.slide-handle[disabled] {
  cursor: not-allowed;
}

/* 自定义类名支持 */
[class*="slide-confirm-container-"] .slide-track {
  @apply [&>div]:rounded-full [&>div]:border-2;
}
</style>